
// Microsoft Office Outlook 2007 Add-in Sample Code
//
// THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// 
using System;
using System.Drawing;
using System.Collections.Generic;
using System.Runtime.InteropServices;

///
/// Outlook requires a specific image format which is different than BMP/JPG, etc.
/// This object support conversion of standard types into the types required by Outlook
/// 
namespace Microsoft.SoftwarePlusServices.ReferenceBits.OutlookPlusServices
{
    ///
    /// <summary>
    /// Convers binary and image data to a IPictureDisp interface using Win32 API functions.
    /// </summary>
    ///
    public static class PictureDispConverter
    {
        #region Private Fields
        private static Guid _iPictureDispGuid = typeof(stdole.IPictureDisp).GUID;
        #endregion

        #region Public Methods

        ///
        /// <summary>
        /// Converts an Icon to a IPictureDisp interface.
        /// </summary>
        /// <param name="icon">The Icon object to convert.</param>
        /// <returns>The IPictureDisp interface representing the image.</returns>
        ///
        public static stdole.IPictureDisp ToIPictureDisp(Icon icon)
        {
            PICTDESC.Icon pictIcon = new PICTDESC.Icon(icon);
            return PictureDispConverter.OleCreatePictureIndirect(pictIcon, ref _iPictureDispGuid, true);
        }

        ///
        /// <summary>
        /// Converts an Image to a IPictureDisp interface.
        /// </summary>
        /// <param name="icon">The Image object to convert.</param>
        /// <returns>The IPictureDisp interface representing the image.</returns>
        ///
        public static stdole.IPictureDisp ToIPictureDisp(Image image)
        {
            Bitmap bitmap = image as Bitmap;
            if (bitmap == null)
                bitmap = new Bitmap(image);

            PICTDESC.Bitmap pictBit = new PICTDESC.Bitmap(bitmap);
            return PictureDispConverter.OleCreatePictureIndirect(pictBit, ref _iPictureDispGuid, true);
        }
        #endregion

        #region Win32 Imports
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1060:MovePInvokesToNativeMethodsClass")]
        [DllImport("OleAut32.dll", EntryPoint = "OleCreatePictureIndirect", ExactSpelling = true, PreserveSig = false)]
        private static extern stdole.IPictureDisp OleCreatePictureIndirect([MarshalAs(UnmanagedType.AsAny)] object picdesc, ref Guid iid, [MarshalAs(UnmanagedType.Bool)] bool fOwn);

        // WINFORMS COMMENT:
        // PICTDESC is a union in native, so we'll just
        // define different ones for the different types
        // the "unused" fields are there to make it the right
        // size, since the struct in native is as big as the biggest
        // union.
        private static class PICTDESC
        {
            //Picture Types
            public const short PICTYPE_UNINITIALIZED = -1;
            public const short PICTYPE_NONE = 0;
            public const short PICTYPE_BITMAP = 1;
            public const short PICTYPE_METAFILE = 2;
            public const short PICTYPE_ICON = 3;
            public const short PICTYPE_ENHMETAFILE = 4;

            [StructLayout(LayoutKind.Sequential)]
            public class Icon
            {
                internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESC.Icon));
                internal int picType = PICTDESC.PICTYPE_ICON;
                internal IntPtr hicon = IntPtr.Zero;
                internal int unused1;
                internal int unused2;

                internal Icon(System.Drawing.Icon icon)
                {
                    this.hicon = icon.ToBitmap().GetHicon();
                }
            }

            [StructLayout(LayoutKind.Sequential)]
            public class Bitmap
            {
                internal int cbSizeOfStruct = Marshal.SizeOf(typeof(PICTDESC.Bitmap));
                internal int picType = PICTDESC.PICTYPE_BITMAP;
                internal IntPtr hbitmap = IntPtr.Zero;
                internal IntPtr hpal = IntPtr.Zero;
                internal int unused;

                internal Bitmap(System.Drawing.Bitmap bitmap)
                {
                    this.hbitmap = bitmap.GetHbitmap();
                }
            }
        }
        #endregion
    }
}
